; NASM 汇编编译器为 bin 文件格式提供了额外的操作符 org
; 它的功能是指定程序被载入内存时的起始地址
; 一句话，就是为程序中所有的内部地址引用增加一个段内偏移值
; 引导程序可以看做是被加载到以 0 为基址的段，偏移为 0x7c00
org 0x7c00

jmp start			; 跳转到 start 标签处运行

start:
    xor ax, ax		; xor 指令与 and or 指令类似，两个操作数的每一对对应位都应用如下操作原则：
					; 如果两个位的值相同（同为 0 或同为 1），则结果位等于 0；否则结果位等于 1
					; xor ax, ax 等于 ax = 0
	mov ss, ax		; 栈段 ss = 0
	mov ds, ax		; 数据段 ds = 0
	mov es, ax		; 附加数据段 es = 0 
	mov sp, 0x7c00	; 设置栈

	; 功能：清屏
	mov ah, 0x06    ; AH 功能号 = 0x06
	mov bh, 0x07    ; 清屏属性
	mov al, 0x00    ; AL = 上卷的行数（如果为0，表示全部）
	mov cx, 0x0000  ; 窗口左上角(CL, CH)位置,即(0, 0)
	mov dx, 0x184f  ; 窗口右下角(DL, DH)位置
					; VGA 文本模式中，一行只能容纳 80 个字节，共 25 行 ，
					; 下标从 0 开始，所以 0x18 =24, 0x4f = 79
	int 0x10

	; 设置光标位置 (dl, dh)
	mov ah, 0x02    ; AH 功能号 = 0x02，设置光标
	mov dh, 0x00    ; 设置光标行号
	mov dl, 0x00    ; 设置光标列号
	mov bh, 0x00    ; 页码
	int 0x10

	mov ax, msg
	mov cx, msgLen
	call print

	jmp $			; 死循环. $ 表示程序当前位置
	

; 显示字符串
; ax : 输入参数，字符串地址
; cx : 输入参数，字符串长度
print:
	; 入栈
	push ax
	push bp
	push bx

	mov bp, ax      ; 保存字符串地址
	mov ax, 0x1301  ; 子功能号 0x13 是写字符串
	mov bx, 000fh   ; 页号位 0，黑底白字
	int 0x10  

	; 出栈
	pop bx
	pop bp
	pop ax

	ret      
	

msg db "Welcome to KOS."	; 使用 db 定义数据
msgLen equ $-msg			; 字符串 msg 长度

times 510-($-$$) db 0x00 	; $ 表示程序当前位置
							; $$ 指代本 section 的起始地址
							; 如果没有定义 section ，nasm 默认全部代码同为一个 section ，起始地址为 0
							; 该指令表示将当前位置到 510 字节处全部填充数据 0x00
db 0x55, 0xaa			 	; 主引导程序最后 2 个字节为 0x55, 0xaa